package com.scut.chenlujie.library.clink.core;

import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;

//封装bytebuffer 否则无止尽的创建 会导致内存爆炸
public class IoArgs {
    private int limit = 256;
    //private byte[] byteBuffer = new byte[5];
    private ByteBuffer buffer = ByteBuffer.allocate(256);

//    public int readFrom(byte[] bytes , int offset){
//        int size = Math.min(bytes.length - offset , buffer.remaining());
//        //把bytes中的数据读到bytebuffer数组中，从bytes中读取数据
//        buffer.put(bytes , offset ,size);
//        return size;
//    }

    public int readFrom(ReadableByteChannel channel) throws IOException{
        int byteProduced = 0;
        while(buffer.hasRemaining()){
            int len = channel.read(buffer);
            if(len < 0){
                throw new EOFException();
            }
            byteProduced += len;
        }

        return byteProduced;
    }

    public int readFrom(byte[] bytes, int offset, int count) {
        int size = Math.min(count, buffer.remaining());
        if (size <= 0) {
            return 0;
        }
        buffer.put(bytes, offset, size);
        return size;
    }

    public int writeTo(byte[] bytes, int offset) {
        int size = Math.min(bytes.length - offset, buffer.remaining());
        buffer.get(bytes, offset, size);
        return size;
    }

    public int writeTo(WritableByteChannel channel) throws IOException{
        int byteProduced = 0;
        while(buffer.hasRemaining()){
            int len = channel.write(buffer);
            if(len < 0){
                throw new EOFException();
            }
            byteProduced += len;
        }
        return byteProduced;
    }
//    public int writeTo(byte[] bytes , int offset){
//        int size = Math.min(bytes.length - offset , buffer.remaining());
//        //把bytebuffer中的数据读到bytes[]数组中,写入数据到bytes中
//        buffer.get(bytes , offset ,size);
//        return size;
//    }

    //从socketChannel读取数据到bytebuffer
    public int readFrom(SocketChannel channel) throws IOException {
        ByteBuffer buffer = this.buffer;
        int byteProduced = 0;
        int len ;
        do{
            len = channel.read(buffer);
            if(len < 0){
                throw new EOFException("cannot read any data with:"+channel);
            }
            byteProduced += len;
        }while(buffer.hasRemaining() && len != 0);

        return byteProduced;
    }

    //写数据到socketChannel中
    public int writeTo(SocketChannel channel) throws  IOException {
        ByteBuffer buffer = this.buffer;
        int byteProduced = 0;
        int len ;
        do{
            len = channel.write(buffer);
            if(len < 0){
                throw new EOFException("current write any data with :"+channel);
            }
            byteProduced += len;
        }while(buffer.hasRemaining() && len != 0);


        return byteProduced;
    }

    //开始写入数据
    public void startWriting(){
        buffer.clear();
        //定义容纳区间
        buffer.limit(limit);
    }

    //设置单次写操作的容纳区间
    public void limit(int limit) {
        this.limit = Math.min(limit, buffer.capacity());
    }

    //写完数据后调用
    public void finishWriting(){
        buffer.flip();
    }

//    public int read(SocketChannel channel) throws IOException {
//        buffer.clear();
//        //从socketChannel把数据读到buffer当中
//        return channel.read(buffer);
//    }
//
//    public int write(SocketChannel channel) throws  IOException {
//        //把buffer中的数据写到channel里面去
//        return channel.write(buffer);
//    }

    public void writeLength(int total) {
        startWriting();
        buffer.putInt(total);
        finishWriting();
    }

    public int  readLength(){
        return buffer.getInt();
    }

    public int capacity() {
        return  buffer.capacity();
    }

//    public String bufferString(){
//        //丢弃换行符 以便string不带有换行符
//        return new String(byteBuffer , 0 , buffer.position()-1 );
//    }


    public boolean remained() {
        return buffer.remaining() > 0;
//        return buffer.hasRemaining();
    }

    public int fllEmpty(int size) {
        int fileSize = Math.min(size, buffer.remaining());
        buffer.position(buffer.position() + fileSize);
        return fileSize;
    }

    public int setEmpty(int size) {
        int emptySize = Math.min(size, buffer.remaining());
        buffer.position(buffer.position() + emptySize);
        return emptySize;
    }



    //这个回调是为了在可发送时再把数据读到IoArgs的，否则现将数据写到IoArgs再去注册，会消耗资源或者拖慢速度
    //IoArgs提供者 处理者, 数据的生产者和消费者
    public interface IoArgsEventProcessor{
        //提供一份可消费的IoArgs
        IoArgs provideIoArgs();
        //sender or receiver消费失败的时候回调
        void onConsumeFailed(IoArgs args , Exception e);

        //sender or receiver消费完成的时候回调
        void onConsumeCompleted(IoArgs args);
    }

    //监听IoArgs的状态
//    public interface IOEventListener {
//        //开始的时候回调
//        void onStarted(IoArgs args);
//
//        //结束的时候回调
//        void onCompleted(IoArgs args);
//    }
}
